package com.tianji.aigc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.aigc.config.SessionProperties;
import com.tianji.aigc.config.SystemPromptConfig;
import com.tianji.aigc.entity.ChatSession;
import com.tianji.aigc.enums.MessageTypeEnum;
import com.tianji.aigc.mapper.ChatSessionMapper;
import com.tianji.aigc.memory.MyAssistantMessage;
import com.tianji.aigc.service.ChatService;
import com.tianji.aigc.service.ChatSessionService;
import com.tianji.aigc.vo.ChatSessionVO;
import com.tianji.aigc.vo.MessageVO;
import com.tianji.aigc.vo.SessionVO;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.MessageType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class ChatSessionServiceImpl extends ServiceImpl<ChatSessionMapper, ChatSession> implements ChatSessionService {
    private final SessionProperties sessionProperties;
    private final ChatMemory redisChatMemory;
    private final ChatClient titleClient;
    private final DashScopeChatModel dashScopeChatModel;

    /**
     * 创建会话
     *
     * @param num 会话数量
     * @return 会话信息
     */
    @Override
    public SessionVO createSession(Integer num) {
        SessionVO sessionVO = BeanUtil.toBean(sessionProperties, SessionVO.class);

        List<SessionVO.Example> examples = RandomUtil.randomEleList(sessionVO.getExamples(), num);

        sessionVO.setExamples(examples);

        String sessionId = IdUtil.simpleUUID();
        sessionVO.setSessionId(sessionId);

        ChatSession chatSession = ChatSession.builder()
                .sessionId(sessionVO.getSessionId())
                .userId(UserContext.getUser())
                .build();
        save(chatSession);
        return sessionVO;
    }

    @Override
    public List<SessionVO.Example> getHotSession(Integer n) {
        return RandomUtil.randomEleList(sessionProperties.getExamples(), n);
    }

    /**
     * 根据会话id查询会话内容
     *
     * @param sessionId 会话id
     * @return 会话内容
     */
    @Override
    public List<MessageVO> queryBySessionId(String sessionId) {
        //通过sessionId获取会话id
        String conversationId = ChatService.getConversationId(sessionId);
        List<Message> messages = redisChatMemory.get(conversationId);
        //将message转成vo
        return messages.stream()
                //过滤 ---> 不弄系统的和工具的
                .filter(message -> message.getMessageType() == MessageType.ASSISTANT || message.getMessageType() == MessageType.USER)
                .map(message -> {
                    if (message instanceof MyAssistantMessage) {
                        return MessageVO.builder()
                                .content(message.getText())
                                .type(MessageTypeEnum.valueOf(message.getMessageType().name()))
                                .params(((MyAssistantMessage) message).getParams())
                                .build();
                    }
                    return MessageVO.builder()
                            .content(message.getText())
                            .type(MessageTypeEnum.valueOf(message.getMessageType().name()))
                            .build();
                })
                .toList();
    }

    @Async//异步执行
    @Override
    public void update(String sessionId, String title, Long userId) {
        ChatSession chatSession = lambdaQuery()
                .eq(ChatSession::getSessionId, sessionId)
                .eq(ChatSession::getUserId, userId)
                .one();
        if (ObjectUtil.isEmpty(chatSession)) {
            return;
        }
        if (StrUtil.isEmpty(chatSession.getTitle()) && StrUtil.isNotBlank(title)) {

            String titleContent = titleClient
                    .prompt()
                    .user(title)
                    .call()
                    .content();
            chatSession.setTitle(titleContent);
        }
        chatSession.setUpdateTime(LocalDateTime.now());
        updateById(chatSession);
    }

    @Override
    public Map<String, List<ChatSessionVO>> queryHistorySession() {
        Long userId = UserContext.getUser();
        List<ChatSession> list = lambdaQuery()
                .eq(ChatSession::getUserId, userId)
                .isNotNull(ChatSession::getTitle)
                .orderByDesc(ChatSession::getUpdateTime)
                .last("limit 30")
                .list();
        if (CollUtil.isEmpty(list)) {
            log.info("用户{}没有历史会话", userId);
            return Map.of();
        }
        //转vo
        List<ChatSessionVO> voList = CollStreamUtil.toList(list, chatSession ->
                ChatSessionVO.builder()
                        .sessionId(chatSession.getSessionId())
                        .updateTime(chatSession.getUpdateTime())
                        .title(chatSession.getTitle())
                        .build()
        );
        final var TODAY = "当天";
        final var LAST_30_DAYS = "最近30天";
        final var LAST_YEAR = "最近1年";
        final var MORE_THAN_YEAR = "1年以上";
        LocalDate now = LocalDate.now();

        Map<String, List<ChatSessionVO>> map = CollStreamUtil.groupByKey(voList, vo -> {
            LocalDate updateTime = vo.getUpdateTime().toLocalDate();
            long between = Math.abs(ChronoUnit.DAYS.between(updateTime, now));
            if (between < 1) {
                return TODAY;
            } else if (between <= 30) {
                return LAST_30_DAYS;
            } else if (between <= 365) {
                return LAST_YEAR;
            } else {
                return MORE_THAN_YEAR;
            }
        });

        return map;
    }

    @Override
    public void deleteHistorySession(String sessionId) {
        Long userId = UserContext.getUser();
        //先删数据库
        ChatSession session = lambdaQuery()
                .eq(ChatSession::getSessionId, sessionId)
                .eq(ChatSession::getUserId, userId)
                .one();
        removeById(session);

        //再删redis
        String conversationId = ChatService.getConversationId(sessionId);
        redisChatMemory.clear(conversationId);

    }

    @Override
    public void updateHistorySession(String sessionId, String title) {
        Long userId = UserContext.getUser();
        ChatSession chatSession = lambdaQuery()
                .eq(ChatSession::getSessionId, sessionId)
                .eq(ChatSession::getUserId, userId)
                .one();
        if (chatSession == null) {
            return;
        }
        if (StrUtil.isNotBlank(title)) {
            chatSession.setTitle(title);
        }
        chatSession.setUpdateTime(LocalDateTime.now());
        updateById(chatSession);
    }
}
